<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>Writing a Switchyard program &#8212; Switchyard 2017.01.5 documentation</title>
    
    <link rel="stylesheet" href="_static/sphinxdoc.css" type="text/css" />
    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
    
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    './',
        VERSION:     '2017.01.5',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true,
        SOURCELINK_SUFFIX: '.txt'
      };
    </script>
    <script type="text/javascript" src="_static/jquery.js"></script>
    <script type="text/javascript" src="_static/underscore.js"></script>
    <script type="text/javascript" src="_static/doctools.js"></script>
    <link rel="index" title="Index" href="genindex.html" />
    <link rel="search" title="Search" href="search.html" />
    <link rel="next" title="Running in the test environment" href="test_execution.html" />
    <link rel="prev" title="Introduction and Overview" href="intro.html" /> 
  </head>
  <body role="document">
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="test_execution.html" title="Running in the test environment"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="intro.html" title="Introduction and Overview"
             accesskey="P">previous</a> |</li>
        <li class="nav-item nav-item-0"><a href="index.html">Switchyard 2017.01.5 documentation</a> &#187;</li> 
      </ul>
    </div>
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
  <h3><a href="index.html">Table Of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">Writing a Switchyard program</a><ul>
<li><a class="reference internal" href="#introducing-the-network-object">Introducing the &#8220;network object&#8221;</a><ul>
<li><a class="reference internal" href="#sending-and-receiving-packets">Sending and receiving packets</a></li>
<li><a class="reference internal" href="#getting-information-about-ports-interfaces-on-the-device">Getting information about ports (interfaces) on the device</a></li>
<li><a class="reference internal" href="#other-methods-on-the-network-object">Other methods on the network object</a></li>
</ul>
</li>
<li><a class="reference internal" href="#introduction-to-packet-parsing-and-construction">Introduction to packet parsing and construction</a></li>
<li><a class="reference internal" href="#utility-functions">Utility functions</a><ul>
<li><a class="reference internal" href="#logging-functions">Logging functions</a></li>
<li><a class="reference internal" href="#invoking-the-debugger">Invoking the debugger</a></li>
</ul>
</li>
<li><a class="reference internal" href="#passing-arguments-into-a-switchyard-program">Passing arguments into a Switchyard program</a></li>
</ul>
</li>
</ul>

  <h4>Previous topic</h4>
  <p class="topless"><a href="intro.html"
                        title="previous chapter">Introduction and Overview</a></p>
  <h4>Next topic</h4>
  <p class="topless"><a href="test_execution.html"
                        title="next chapter">Running in the test environment</a></p>
  <div role="note" aria-label="source link">
    <h3>This Page</h3>
    <ul class="this-page-menu">
      <li><a href="_sources/writing_a_program.rst.txt"
            rel="nofollow">Show Source</a></li>
    </ul>
   </div>
<div id="searchbox" style="display: none" role="search">
  <h3>Quick search</h3>
    <form class="search" action="search.html" method="get">
      <div><input type="text" name="q" /></div>
      <div><input type="submit" value="Go" /></div>
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body" role="main">
            
  <div class="section" id="writing-a-switchyard-program">
<span id="coding"></span><h1>Writing a Switchyard program<a class="headerlink" href="#writing-a-switchyard-program" title="Permalink to this headline">¶</a></h1>
<p id="index-0">A Switchyard program is simply a Python program that includes a particular entrypoint function which accepts a single parameter.  The startup function can simply be named <code class="docutils literal"><span class="pre">main</span></code>, but can also be named <code class="docutils literal"><span class="pre">switchy_main</span></code> if you like.  The function must accept at least one parameter, which is a reference to the Switchyard <em>network object</em> (described below).  Method calls on the network object are used to send and receive packets to and from network ports.</p>
<p id="index-1">A Switchyard program isn&#8217;t executed <em>directly</em> with the Python interpreter.  Instead, the program <code class="docutils literal"><span class="pre">swyard</span></code> is used to start up the Switchyard framework and to load your code.  When Switchyard starts your code it looks for a function named <code class="docutils literal"><span class="pre">main</span></code> and invokes it, passing in the network object as the first parameter.  Details on how to start Switchyard (and thus your program) are given in the chapters on <a class="reference internal" href="test_execution.html#runtest"><span class="std std-ref">running a Switchyard in the test environment</span></a> and <a class="reference internal" href="live_execution.html#runlive"><span class="std std-ref">running Switchyard in a live environment</span></a>.  Note that it is possible to pass arguments into a Switchyard program; see <a class="reference internal" href="#swyardargs"><span class="std std-ref">Passing arguments into a Switchyard program</span></a> for details.</p>
<p>A Switchyard program will typically also import other Switchyard modules such as modules for parsing and constructing packets, dealing with network addresses, and other functions.  These modules are introduced below and described in detail in the <a class="reference internal" href="reference.html#apiref"><span class="std std-ref">API reference chapter</span></a>.</p>
<div class="section" id="introducing-the-network-object">
<h2>Introducing the &#8220;network object&#8221;<a class="headerlink" href="#introducing-the-network-object" title="Permalink to this headline">¶</a></h2>
<p>As mentioned above, a Switchyard program can simply have a <code class="docutils literal"><span class="pre">main</span></code> function that accepts a single argument.  The parameter passed to <code class="docutils literal"><span class="pre">main</span></code> is called the &#8220;network object&#8221;.  It is on this object that you can call methods for sending and receiving packets and getting information about ports on the device for which you&#8217;re implementing the logic.</p>
<div class="section" id="sending-and-receiving-packets">
<h3>Sending and receiving packets<a class="headerlink" href="#sending-and-receiving-packets" title="Permalink to this headline">¶</a></h3>
<p>As a way to describe two of the most important methods on the network object, here is a program that receives one packet, prints it out, sends it <em>back out the same interface</em>, then quits.</p>
<p>Notice in the code below that we only need to import <a class="reference internal" href="reference.html#module-switchyard.lib.userlib" title="switchyard.lib.userlib"><code class="xref py py-mod docutils literal"><span class="pre">switchyard.lib.userlib</span></code></a> to get access to various Switchyard classes and functions; generally speaking, this is the <em>only</em> import you should ever need for any Switchyard program.  Although you can import individual Switchyard modules separately (for the specific module to import, see <a class="reference internal" href="reference.html#apiref"><span class="std std-ref">API Reference</span></a>), but you will probably find that importing <code class="docutils literal"><span class="pre">userlib</span></code> is much easier.</p>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">switchyard.lib.userlib</span> <span class="kn">import</span> <span class="o">*</span>

<span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="n">net</span><span class="p">):</span>
    <span class="n">timestamp</span><span class="p">,</span><span class="n">input_port</span><span class="p">,</span><span class="n">packet</span> <span class="o">=</span> <span class="n">net</span><span class="o">.</span><span class="n">recv_packet</span><span class="p">()</span>
    <span class="k">print</span> <span class="p">(</span><span class="s2">&quot;Received {} on {}&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">packet</span><span class="p">,</span> <span class="n">input_port</span><span class="p">))</span>
    <span class="n">net</span><span class="o">.</span><span class="n">send_packet</span><span class="p">(</span><span class="n">input_port</span><span class="p">,</span> <span class="n">packet</span><span class="p">)</span>
</pre></div>
</div>
<p>This program isn&#8217;t likely to be very useful &#8212; it is just meant as an illustration of the most important two methods on the network object:</p>
<blockquote>
<div><ul>
<li><p class="first"><code class="docutils literal"><span class="pre">recv_packet(timeout=None)</span></code></p>
<p>Not surprisingly, this method is used to receive at most one packet from any port.  The method will <em>block</em> until a packet is received, unless a timeout value &gt;=0 is given.  The default is to block indefinitely.  The method returns a <em>namedtuple</em> of length 3, which includes a timestamp for when the packet was received, the name of the input port on which the packet was received, and the packet itself (another example is given below, plus see <code class="xref py py-class docutils literal"><span class="pre">collections.namedtuple</span></code> in the Python library reference).</p>
<p>The method raises a <code class="docutils literal"><span class="pre">Shutdown</span></code> exception if the Switchyard framework has been shut down.  It can also raise a <code class="docutils literal"><span class="pre">NoPackets</span></code> exception if no packets are received before the timeout value given to the method expires.</p>
</li>
<li><p class="first"><code class="docutils literal"><span class="pre">send_packet(output_port,</span> <span class="pre">packet)</span></code></p>
<p>Again, the meaning of this method call is probably not especially surprising: when called, the given packet will be sent out the given output port.  For the <code class="docutils literal"><span class="pre">output_port</span></code> parameter, the string name of the port can be given, or an <code class="docutils literal"><span class="pre">Interface</span></code> object may also be supplied (see below for <a class="reference internal" href="#intf-overview"><span class="std std-ref">more about Interface objects</span></a> as well as the <a class="reference internal" href="reference.html#intf-detail"><span class="std std-ref">Interface and InterfaceType reference</span></a>).</p>
<p>This method returns <code class="docutils literal"><span class="pre">None</span></code>.  If the <code class="docutils literal"><span class="pre">output_port</span></code> or some detail about the given packet is invalid (e.g., something other than a packet is passed as the second parameter), this method raises a <code class="docutils literal"><span class="pre">ValueError</span></code>.</p>
</li>
</ul>
</div></blockquote>
<p id="index-2">Returning briefly to the <code class="docutils literal"><span class="pre">recv_packet</span></code> method, observe that in the above example no arguments are given so the call will block until a packet is received.  Also, it is important to recognize that the return type of <code class="docutils literal"><span class="pre">recv_packet</span></code> is a <em>namedtuple</em> of exactly three elements so in addition to automatically unpacking the tuple as in the above example, you can use indexing or attribute-like syntax on the return value from <code class="docutils literal"><span class="pre">recv_packet</span></code>.  For example (using attribute-syntax):</p>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">switchyard.lib.userlib</span> <span class="kn">import</span> <span class="o">*</span>

<span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="n">net</span><span class="p">):</span>
    <span class="c1"># below, recvdata is a namedtuple</span>
    <span class="n">recvdata</span> <span class="o">=</span> <span class="n">net</span><span class="o">.</span><span class="n">recv_packet</span><span class="p">()</span>
    <span class="k">print</span> <span class="p">(</span><span class="s2">&quot;At {}, received {} on {}&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
        <span class="n">recvdata</span><span class="o">.</span><span class="n">timestamp</span><span class="p">,</span> <span class="n">recvdata</span><span class="o">.</span><span class="n">packet</span><span class="p">,</span> <span class="n">recvdata</span><span class="o">.</span><span class="n">input_port</span><span class="p">))</span>

    <span class="c1"># alternatively, the above line could use indexing, although</span>
    <span class="c1"># readability suffers:</span>
    <span class="c1">#    recvdata[0], recvdata[2], recvdata[1]))</span>
    
    <span class="n">net</span><span class="o">.</span><span class="n">send_packet</span><span class="p">(</span><span class="n">recvdata</span><span class="o">.</span><span class="n">input_port</span><span class="p">,</span> <span class="n">recvdata</span><span class="o">.</span><span class="n">packet</span><span class="p">)</span>

    <span class="c1"># likewise, the above line could be written using indexing</span>
    <span class="c1"># but, again, readability suffers:</span>
    <span class="c1"># net.send_packet(recvdata[1], recvdata[2])</span>
</pre></div>
</div>
<p>Importantly, note that in the above examples we are not handling any potential exceptions that could occur.  In particular, we really should be handling <em>at least</em> the situation in which the framework is shut down (and we receive a <code class="docutils literal"><span class="pre">Shutdown</span></code> exception).  Just for completeness, we should also handle the <code class="docutils literal"><span class="pre">NoPackets</span></code> exception, although if the code is designed to block indefinitely we shouldn&#8217;t normally receive that particular exception.</p>
<p>Let&#8217;s rewrite the code above, and now put everything in a <code class="docutils literal"><span class="pre">while</span></code> loop so that we keep reading and sending packets as long as we&#8217;re running.  We will eventually turn this code into a working network <em>hub</em> implementation <a class="footnote-reference" href="#f1" id="id1">[1]</a>, but it&#8217;s currently broken because it still just sends a packet out the <em>same port</em> on which it arrived:</p>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">switchyard.lib.userlib</span> <span class="kn">import</span> <span class="o">*</span>

<span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="n">net</span><span class="p">):</span>
    <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">timestamp</span><span class="p">,</span><span class="n">input_port</span><span class="p">,</span><span class="n">packet</span> <span class="o">=</span> <span class="n">net</span><span class="o">.</span><span class="n">recv_packet</span><span class="p">()</span>
        <span class="k">except</span> <span class="n">Shutdown</span><span class="p">:</span>
            <span class="n">log_info</span> <span class="p">(</span><span class="s2">&quot;Got shutdown signal; exiting&quot;</span><span class="p">)</span>
            <span class="k">break</span>
        <span class="k">except</span> <span class="n">NoPackets</span><span class="p">:</span>
            <span class="n">log_info</span> <span class="p">(</span><span class="s2">&quot;No packets were available.&quot;</span><span class="p">)</span>
            <span class="k">continue</span>

        <span class="c1"># if we get here, we must have received a packet</span>
        <span class="n">log_info</span> <span class="p">(</span><span class="s2">&quot;Received {} on {}&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">packet</span><span class="p">,</span> <span class="n">input_port</span><span class="p">))</span>
        <span class="n">net</span><span class="o">.</span><span class="n">send_packet</span><span class="p">(</span><span class="n">input_port</span><span class="p">,</span> <span class="n">packet</span><span class="p">)</span>
</pre></div>
</div>
<p id="index-3">In the example above, notice that we also changed the <code class="docutils literal"><span class="pre">print</span></code> function calls to <code class="docutils literal"><span class="pre">log_info</span></code>.  Switchyard uses built-in Python logging capabilities (see <code class="xref py py-mod docutils literal"><span class="pre">logging</span></code> in the Python library reference) for printing various notices to the console.  The <a class="reference internal" href="#logging-label"><span class="std std-ref">logging functions</span></a>, described below, each just accept one string parameter which is just the text to be printed on the console.</p>
<p>For full details of the <code class="docutils literal"><span class="pre">send_packet</span></code> and <code class="docutils literal"><span class="pre">recv_packet</span></code> method calls, refer to <a class="reference internal" href="reference.html#netobj"><span class="std std-ref">Net object reference</span></a> in the <a class="reference internal" href="reference.html#apiref"><span class="std std-ref">API Reference</span></a> section at the end of this documentation.</p>
</div>
<div class="section" id="getting-information-about-ports-interfaces-on-the-device">
<span id="intf-overview"></span><h3>Getting information about ports (interfaces) on the device<a class="headerlink" href="#getting-information-about-ports-interfaces-on-the-device" title="Permalink to this headline">¶</a></h3>
<p>Other methods available the network object relate to getting information about the ports/interfaces attached to the device on which the Switchyard code is running.  The two basic methods are <code class="docutils literal"><span class="pre">interfaces</span></code> and <code class="docutils literal"><span class="pre">ports</span></code>.  These methods are aliases and do exactly the same thing.  In particular:</p>
<blockquote>
<div><ul>
<li><p class="first"><code class="docutils literal"><span class="pre">interfaces()</span></code></p>
<p>This method returns a list of interfaces that are configured on the network device, as a list of <code class="docutils literal"><span class="pre">Interface</span></code> objects.  The alias method <code class="docutils literal"><span class="pre">ports()</span></code> does exactly the same thing.  There is no inherent ordering to the list of <code class="docutils literal"><span class="pre">Interface</span></code> objects returned.</p>
</li>
</ul>
</div></blockquote>
<p>Each <code class="docutils literal"><span class="pre">Interface</span></code> object has a set of properties that can be used to access various configured attributes for the interface:</p>
<blockquote>
<div><ul class="simple">
<li><code class="docutils literal"><span class="pre">name</span></code>: returns the name of the interface (e.g., <code class="docutils literal"><span class="pre">en0</span></code>) as a string.</li>
<li><code class="docutils literal"><span class="pre">ethaddr</span></code>: returns the Ethernet address associated with the interface, as a <a class="reference internal" href="reference.html#switchyard.lib.address.EthAddr" title="switchyard.lib.address.EthAddr"><code class="xref py py-class docutils literal"><span class="pre">switchyard.lib.address.EthAddr</span></code></a> instance.</li>
<li><code class="docutils literal"><span class="pre">ipaddr</span></code>: returns the IPv4 address associated with the interface, if any.  This property returns an object of type <code class="xref py py-class docutils literal"><span class="pre">IPv4Address</span></code>.  If there is no address assigned to the interface, the address is 0.0.0.0.  A current limitation with the <code class="docutils literal"><span class="pre">Interface</span></code> implementation in Switchyard is that only one address can be associated with an interface, and it must be an IPv4 address.  Eventually, Switchyard will fully support IPv6 addresses, and multiple IP addresses per interface.</li>
<li><code class="docutils literal"><span class="pre">netmask</span></code>: returns the network mask associated with the IPv4 address assigned to the interface.  The netmask defaults to 255.255.255.255 (/32) if none is specified.</li>
<li><code class="docutils literal"><span class="pre">ifnum</span></code>: returns an integer index associated with the interface.</li>
<li><code class="docutils literal"><span class="pre">iftype</span></code>: returns the type of the interface, if it can be inferred by Switchyard.  The return type is a value from the <a class="reference internal" href="reference.html#switchyard.lib.interface.InterfaceType" title="switchyard.lib.interface.InterfaceType"><code class="xref py py-class docutils literal"><span class="pre">switchyard.lib.interface.InterfaceType</span></code></a> enumerated type.  The type can either be <code class="docutils literal"><span class="pre">Unknown</span></code>, <code class="docutils literal"><span class="pre">Loopback</span></code>, <code class="docutils literal"><span class="pre">Wired</span></code>, or <code class="docutils literal"><span class="pre">Wireless</span></code>.  The type is automatically set when an interface is initialized.  Note that in some cases the type can be inferred, but in others it cannot (thus the potential for an <code class="docutils literal"><span class="pre">Unknown</span></code> value).</li>
</ul>
</div></blockquote>
<p>All the above properties except <code class="docutils literal"><span class="pre">ifnum</span></code> and <code class="docutils literal"><span class="pre">iftype</span></code> are modifiable.  Changing them can be accomplished just by assigning a new value to the property.  Beware, though, that changing address values has no effect on the underlying host operating system if Switchyard is run in a live environment, so you would generally be wise to leave the addresses alone.</p>
<p>For full interface details, see <a class="reference internal" href="reference.html#intf-detail"><span class="std std-ref">Interface and InterfaceType reference</span></a>.</p>
<p>As an example, to simply print out information regarding each interface defined on the current network device you could use the following program:</p>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="n">net</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">intf</span> <span class="ow">in</span> <span class="n">net</span><span class="o">.</span><span class="n">interfaces</span><span class="p">():</span>
        <span class="n">log_info</span><span class="p">(</span><span class="s2">&quot;{} has ethaddr {} and ipaddr {}/{} and is of type {}&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
            <span class="n">intf</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">intf</span><span class="o">.</span><span class="n">ethaddr</span><span class="p">,</span> <span class="n">intf</span><span class="o">.</span><span class="n">ipaddr</span><span class="p">,</span> <span class="n">intf</span><span class="o">.</span><span class="n">netmask</span><span class="p">,</span> <span class="n">intf</span><span class="o">.</span><span class="n">iftype</span><span class="o">.</span><span class="n">name</span><span class="p">))</span>

    <span class="c1"># could also be:</span>
    <span class="c1"># for intf in net.ports():</span>
    <span class="c1">#    ...</span>
</pre></div>
</div>
<p>Entirely depending on how the network device is configured, output from
the above program might look like the following:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="mi">09</span><span class="p">:</span><span class="mi">10</span><span class="p">:</span><span class="mi">08</span> <span class="mi">2016</span><span class="o">/</span><span class="mi">12</span><span class="o">/</span><span class="mi">17</span>     <span class="n">INFO</span> <span class="n">eth0</span> <span class="n">has</span> <span class="n">ethaddr</span> <span class="mi">10</span><span class="p">:</span><span class="mi">00</span><span class="p">:</span><span class="mi">00</span><span class="p">:</span><span class="mi">00</span><span class="p">:</span><span class="mi">00</span><span class="p">:</span><span class="mi">01</span> <span class="ow">and</span> <span class="n">ipaddr</span> <span class="mf">172.16</span><span class="o">.</span><span class="mf">42.1</span><span class="o">/</span><span class="mf">255.255</span><span class="o">.</span><span class="mf">255.252</span> <span class="ow">and</span> <span class="ow">is</span> <span class="n">of</span> <span class="nb">type</span> <span class="n">Unknown</span>
<span class="mi">09</span><span class="p">:</span><span class="mi">10</span><span class="p">:</span><span class="mi">08</span> <span class="mi">2016</span><span class="o">/</span><span class="mi">12</span><span class="o">/</span><span class="mi">17</span>     <span class="n">INFO</span> <span class="n">eth1</span> <span class="n">has</span> <span class="n">ethaddr</span> <span class="mi">10</span><span class="p">:</span><span class="mi">00</span><span class="p">:</span><span class="mi">00</span><span class="p">:</span><span class="mi">00</span><span class="p">:</span><span class="mi">00</span><span class="p">:</span><span class="mi">02</span> <span class="ow">and</span> <span class="n">ipaddr</span> <span class="mf">10.10</span><span class="o">.</span><span class="mf">0.1</span><span class="o">/</span><span class="mf">255.255</span><span class="o">.</span><span class="mf">0.0</span> <span class="ow">and</span> <span class="ow">is</span> <span class="n">of</span> <span class="nb">type</span> <span class="n">Unknown</span>
<span class="mi">09</span><span class="p">:</span><span class="mi">10</span><span class="p">:</span><span class="mi">08</span> <span class="mi">2016</span><span class="o">/</span><span class="mi">12</span><span class="o">/</span><span class="mi">17</span>     <span class="n">INFO</span> <span class="n">eth2</span> <span class="n">has</span> <span class="n">ethaddr</span> <span class="mi">10</span><span class="p">:</span><span class="mi">00</span><span class="p">:</span><span class="mi">00</span><span class="p">:</span><span class="mi">00</span><span class="p">:</span><span class="mi">00</span><span class="p">:</span><span class="mi">03</span> <span class="ow">and</span> <span class="n">ipaddr</span> <span class="mf">192.168</span><span class="o">.</span><span class="mf">1.1</span><span class="o">/</span><span class="mf">255.255</span><span class="o">.</span><span class="mf">255.0</span> <span class="ow">and</span> <span class="ow">is</span> <span class="n">of</span> <span class="nb">type</span> <span class="n">Unknown</span>
</pre></div>
</div>
<p>The above example code was run in the <a class="reference internal" href="test_execution.html#runtest"><span class="std std-ref">Switchyard *test* environment</span></a>; when a Switchyard program is run in test mode, all interfaces will show type <code class="docutils literal"><span class="pre">Unknown</span></code>.  Note also that there is <em>no inherent ordering</em> to the list of interfaces returned.</p>
<p>There are a few convenience methods related to <code class="docutils literal"><span class="pre">ports</span></code> and <code class="docutils literal"><span class="pre">interfaces</span></code>,
which can be used to look up a particular interface given a name, IPv4 address,
or Ethernet (MAC) address:</p>
<blockquote>
<div><ul class="simple">
<li><code class="docutils literal"><span class="pre">interface_by_name(name)</span></code>: This method returns an <code class="docutils literal"><span class="pre">Interface</span></code> object given a string name
of a interface.  An alias method <code class="docutils literal"><span class="pre">port_by_name(name)</span></code> also exists.</li>
<li><code class="docutils literal"><span class="pre">interface_by_ipaddr(ipaddr)</span></code>: This method returns an <code class="docutils literal"><span class="pre">Interface</span></code> object given an IP address configured on one of the interfaces.  The IP address may be given as a string or as an IPv4Address object.  An alias method <code class="docutils literal"><span class="pre">port_by_ipaddr(ipaddr)</span></code> also exists.</li>
<li><code class="docutils literal"><span class="pre">interface_by_macaddr(ethaddr)</span></code>: This method returns an <code class="docutils literal"><span class="pre">Interface</span></code> object given an Ethernet (MAC) address configured on one of the interfaces.  An alias method <code class="docutils literal"><span class="pre">port_by_macaddr(ethaddr)</span></code> also exists.</li>
</ul>
</div></blockquote>
<p>Note that the above lookup methods raise a <code class="docutils literal"><span class="pre">KeyError</span></code> exception if the lookup name is invalid.</p>
</div>
<div class="section" id="other-methods-on-the-network-object">
<h3>Other methods on the network object<a class="headerlink" href="#other-methods-on-the-network-object" title="Permalink to this headline">¶</a></h3>
<p>Lastly, there is a <code class="docutils literal"><span class="pre">shutdown</span></code> method available on the network object.  This method should be used by a Switchyard program prior to exiting in order to clean up and shut down various resources.</p>
<p>Let&#8217;s now add a bit to the previous example program to turn it into an almost-complete implementation of a hub.  Whenever we receive a packet, we need to loop through the ports on the device and send the packet on a port as long as the port isn&#8217;t the one on which we received the packet (lines 21-23, below):</p>
<div class="literal-block-wrapper docutils container" id="id4">
<div class="code-block-caption"><span class="caption-text">A (nearly) full implementation of a hub.</span><a class="headerlink" href="#id4" title="Permalink to this code">¶</a></div>
<div class="highlight-python"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">switchyard.lib.userlib</span> <span class="kn">import</span> <span class="o">*</span>

<span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="n">net</span><span class="p">):</span>
    <span class="c1"># add some informational text about ports on this device</span>
    <span class="n">log_info</span> <span class="p">(</span><span class="s2">&quot;Hub is starting up with these ports:&quot;</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">port</span> <span class="ow">in</span> <span class="n">net</span><span class="o">.</span><span class="n">ports</span><span class="p">():</span>
        <span class="n">log_info</span> <span class="p">(</span><span class="s2">&quot;{}: ethernet address {}&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">port</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">port</span><span class="o">.</span><span class="n">ethaddr</span><span class="p">))</span>

    <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">timestamp</span><span class="p">,</span><span class="n">input_port</span><span class="p">,</span><span class="n">packet</span> <span class="o">=</span> <span class="n">net</span><span class="o">.</span><span class="n">recv_packet</span><span class="p">()</span>
        <span class="k">except</span> <span class="n">Shutdown</span><span class="p">:</span>
            <span class="c1"># got shutdown signal</span>
            <span class="k">break</span>
        <span class="k">except</span> <span class="n">NoPackets</span><span class="p">:</span>
            <span class="c1"># try again...</span>
            <span class="k">continue</span>

        <span class="c1"># send the packet out all ports *except*</span>
        <span class="c1"># the one on which it arrived</span>
        <span class="k">for</span> <span class="n">port</span> <span class="ow">in</span> <span class="n">net</span><span class="o">.</span><span class="n">ports</span><span class="p">():</span>
            <span class="k">if</span> <span class="n">port</span><span class="o">.</span><span class="n">name</span> <span class="o">!=</span> <span class="n">input_port</span><span class="p">:</span>
                <span class="n">net</span><span class="o">.</span><span class="n">send_packet</span><span class="p">(</span><span class="n">port</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">packet</span><span class="p">)</span>

    <span class="c1"># shutdown is the last thing we should do</span>
    <span class="n">net</span><span class="o">.</span><span class="n">shutdown</span><span class="p">()</span>
</pre></div>
</td></tr></table></div>
</div>
<p>There&#8217;s still one thing missing from the above code, which is for the hub to ignore any frames that are destined to the hub itself.  That is, if an Ethernet destination address in a received frame is the same as an Ethernet address assigned to one of the ports on the hub, the frame should <em>not</em> be forwarded (it can simply be ignored).  Finishing off the hub by doing this is left as an exercise.</p>
</div>
</div>
<div class="section" id="introduction-to-packet-parsing-and-construction">
<h2>Introduction to packet parsing and construction<a class="headerlink" href="#introduction-to-packet-parsing-and-construction" title="Permalink to this headline">¶</a></h2>
<p>This section provides an overview of packet construction and parsing in Switchyard.  For full details on these capabilities, see <a class="reference internal" href="reference.html#pktlib"><span class="std std-ref">Packet parsing and construction reference</span></a>.</p>
<p>Switchyard&#8217;s packet construction/parsing library is found in <code class="docutils literal"><span class="pre">switchyard.lib.packet</span></code>.  Its design is based on a few other libraries out there, including POX&#8217;s library <a class="footnote-reference" href="#f2" id="id2">[2]</a> and Ryu&#8217;s library <a class="footnote-reference" href="#f3" id="id3">[3]</a>.</p>
<p>There are a few key ideas to understand when using the packet library:</p>
<blockquote>
<div><ul class="simple">
<li>The <code class="docutils literal"><span class="pre">Packet</span></code> class acts as a container of headers (or rather, of header objects).</li>
<li>Headers within a packet can be accessed through methods on the Packet container object, and also by indexing.  Headers are ordered starting with lowest layer protocols.  For example, if a <code class="docutils literal"><span class="pre">Packet</span></code> has an <code class="docutils literal"><span class="pre">Ethernet</span></code> header (which is likely to be the lowest layer protocol), this header can be accessed with index 0 as in <code class="docutils literal"><span class="pre">pktobj[0]</span></code>.  Indexes can be integers, and they can also be packet header class names (e.g., <code class="docutils literal"><span class="pre">Ethernet</span></code>, <code class="docutils literal"><span class="pre">IPv4</span></code>, etc.).  For example, to access the <code class="docutils literal"><span class="pre">Ethernet</span></code> header of a packet, you can write <code class="docutils literal"><span class="pre">pktobj[Ethernet]</span></code>.</li>
<li>Fields in header objects are accessed through standard Python <em>properties</em>.  The code to manipulate header fields thus looks like it is just accessing instance variables, but &#8220;getter&#8221; and &#8220;setter&#8221; method calls actually take place, depending on whether a property is being retrieved or assigned to.</li>
<li>A packet object can be constructed by either expliciting instantiating an object and adding headers, or it can be formed by &#8220;adding&#8221; (using the <code class="docutils literal"><span class="pre">+</span></code> operator) headers together, or by appending headers onto a packet (using <code class="docutils literal"><span class="pre">+</span></code> or <code class="docutils literal"><span class="pre">+=</span></code>).</li>
<li>The Switchyard framework generally <em>automatically</em> handles serializing and deserializing Packet objects to and from byte sequences (i.e., wire format packets), but you can also explicitly invoke those methods if you need to.</li>
</ul>
</div></blockquote>
<div class="figure align-center">
<img alt="_images/packet.png" src="_images/packet.png" />
</div>
<p>Here are some examples using <code class="docutils literal"><span class="pre">Ethernet</span></code>, <code class="docutils literal"><span class="pre">IPv4</span></code>, and <code class="docutils literal"><span class="pre">ICMP</span></code> headers. First, let&#8217;s construct a packet object and add these headers to the packet:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">switchyard.lib.packet</span> <span class="k">import</span> <span class="o">*</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">Packet</span><span class="p">()</span>   <span class="c1"># construct a packet object</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">e</span> <span class="o">=</span> <span class="n">Ethernet</span><span class="p">()</span> <span class="c1"># construct Ethernet header</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ip</span> <span class="o">=</span> <span class="n">IPv4</span><span class="p">()</span>    <span class="c1"># construct IPv4 header</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">icmp</span> <span class="o">=</span> <span class="n">ICMP</span><span class="p">()</span>  <span class="c1"># construct ICMP header</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">+=</span> <span class="n">e</span>         <span class="c1"># add eth header to packet</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">+=</span> <span class="n">ip</span>        <span class="c1"># add ip header to packet</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">+=</span> <span class="n">icmp</span>      <span class="c1"># add icmp header to packet</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span> <span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="go">Ethernet 00:00:00:00:00:00-&gt;00:00:00:00:00:00 IP | IPv4 0.0.0.0-&gt;0.0.0.0 ICMP | ICMP EchoRequest 0 0 (0 data bytes)</span>
</pre></div>
</div>
<p>A shorthand for doing the above is:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">Ethernet</span><span class="p">()</span> <span class="o">+</span> <span class="n">IPv4</span><span class="p">()</span> <span class="o">+</span> <span class="n">ICMP</span><span class="p">()</span>
</pre></div>
</div>
<p>The effect of the <code class="docutils literal"><span class="pre">+</span></code> operator with header objects as in the previous line is to construct a packet object, just as the first example.  Note that with the above one-line example, the default Ethertype for the Ethernet header is IPv4, and the default protocol number for IPv4 is ICMP.  Thus, this example is somewhat special in that we didn&#8217;t need to modify any of the packet header fields to create a (mostly) valid packet.  Lastly, note that the order in which we add packet headers together to construct a full packet is important: lower layers (e.g., <code class="docutils literal"><span class="pre">Ethernet</span></code>) must come first, followed by other protocol headers in their correct order.</p>
<p>Switchyard does <em>not</em> ensure that a constructed Packet is sensible in any way.  It is possible to put headers in the wrong order, to supply illogical values for header elements (e.g., a protocol number in the IPv4 header that doesn&#8217;t match the next header in the packet), and to do other invalid things.  Switchyard gives you the tools for constructing packets, but doesn&#8217;t tell you how to do so.</p>
<p>The <code class="docutils literal"><span class="pre">num_headers</span></code> Packet method returns the number of headers in a packet, which returns the expected number for this example:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">num_headers</span><span class="p">()</span>
<span class="go">3</span>
</pre></div>
</div>
<p>Note that the <code class="docutils literal"><span class="pre">len</span></code> function on a packet returns the number of <em>bytes</em> that the Packet would consume if it was in wire (serialized) format.  The <code class="docutils literal"><span class="pre">size</span></code> method returns the same value.</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">len</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="go">42</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">size</span><span class="p">()</span>
<span class="go">42</span>
</pre></div>
</div>
<p>(Note: Ethernet header is 14 bytes + 20 bytes IP + 8 bytes ICMP = 42 bytes.)</p>
<p>Packet header objects can be accessed conveniently by indexing.  Standard negative indexing also works.  For example, to obtain a reference to the Ethernet header object and to inspect and modify the Ethernet header, we might do the following:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="c1"># access by index</span>
<span class="go">&lt;switchyard.lib.packet.ethernet.Ethernet object at 0x104474248&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">src</span>
<span class="go">EthAddr(&#39;00:00:00:00:00:00&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">dst</span>
<span class="go">EthAddr(&#39;00:00:00:00:00:00&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">dst</span> <span class="o">=</span> <span class="s2">&quot;ab:cd:ef:00:11:22&quot;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">str</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="go">&#39;Ethernet 00:00:00:00:00:00-&gt;ab:cd:ef:00:11:22 IP&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">dst</span> <span class="o">=</span> <span class="n">EthAddr</span><span class="p">(</span><span class="s2">&quot;00:11:22:33:44:55&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">str</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="go">&#39;Ethernet 00:00:00:00:00:00-&gt;00:11:22:33:44:55 IP&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">ethertype</span>
<span class="go">&lt;EtherType.IP: 2048&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">ethertype</span> <span class="o">=</span> <span class="n">EtherType</span><span class="o">.</span><span class="n">ARP</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span> <span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="go">Ethernet 00:00:00:00:00:00-&gt;00:00:00:00:00:00 ARP | IPv4 0.0.0.0-&gt;0.0.0.0 ICMP | ICMP EchoRequest 0 0 (0 data bytes)</span>
<span class="go">&gt;&gt; p[0].ethertype = EtherType.IPv4 # set it back to sensible value</span>
</pre></div>
</div>
<p>Note that all header field elements are accessed through <em>properties</em>.  For Ethernet headers, there are three properties that can be inspected and modified, <code class="docutils literal"><span class="pre">src</span></code>, <code class="docutils literal"><span class="pre">dst</span></code> and <code class="docutils literal"><span class="pre">ethertype</span></code>, as shown above.  Notice also that Switchyard doesn&#8217;t prevent a user from setting header fields to illogical values, e.g., when we set the ethertype to ARP although the next header is IPv4, not ARP.  All <code class="docutils literal"><span class="pre">EtherType</span></code> values are specified in <code class="docutils literal"><span class="pre">switchyard.lib.packet.common</span></code>, and imported when the module <code class="docutils literal"><span class="pre">switchyard.lib.packet</span></code> is imported.</p>
<p>Accessing header fields in other headers works similarly.  Here are examples involving the IPv4 header:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">has_header</span><span class="p">(</span><span class="n">IPv4</span><span class="p">)</span>
<span class="go">True</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">get_header_index</span><span class="p">(</span><span class="n">IPv4</span><span class="p">)</span>
<span class="go">1</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">str</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="c1"># access by index</span>
<span class="go">&#39;IPv4 0.0.0.0-&gt;0.0.0.0 ICMP&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">str</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="n">IPv4</span><span class="p">])</span> <span class="c1"># access by header type</span>
<span class="go">&#39;IPv4 0.0.0.0-&gt;0.0.0.0 ICMP&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="p">[</span><span class="n">IPv4</span><span class="p">]</span><span class="o">.</span><span class="n">protocol</span>
<span class="go">&lt;IPProtocol.ICMP: 1&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="p">[</span><span class="n">IPv4</span><span class="p">]</span><span class="o">.</span><span class="n">src</span>
<span class="go">IPv4Address(&#39;0.0.0.0&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="p">[</span><span class="n">IPv4</span><span class="p">]</span><span class="o">.</span><span class="n">dst</span>
<span class="go">IPv4Address(&#39;0.0.0.0&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="p">[</span><span class="n">IPv4</span><span class="p">]</span><span class="o">.</span><span class="n">dst</span> <span class="o">=</span> <span class="s1">&#39;149.43.80.13&#39;</span>
</pre></div>
</div>
<p>IPv4 protocol values are specified in <code class="docutils literal"><span class="pre">switchyard.lib.packet.common</span></code>, just as with <code class="docutils literal"><span class="pre">EtherType</span></code> values.  Note, however, that you do not need to explicitly import this module if you import <code class="docutils literal"><span class="pre">switchyard.lib.userlib</span></code> &#8212; packet-related classes and enumerations are imported when importing <code class="docutils literal"><span class="pre">userlib</span></code>. The full set of properties that can be manipulated in the IPv4 header as well as all other headers is described in the <a class="reference internal" href="reference.html#pktlib"><span class="std std-ref">reference documentation for the packet library</span></a>.</p>
<p>Lastly, an example with the ICMP header shows some perhaps now familiar patterns.  The main difference with ICMP is that the &#8220;data&#8221; portion of an ICMP packet changes, depending on the ICMP type.  For example, if the type is 8 (ICMP echo request) the ICMP data becomes an object that allows the identifier and sequence values to be inspected and modified.</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">has_header</span><span class="p">(</span><span class="n">ICMP</span><span class="p">)</span>
<span class="go">True</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">get_header_index</span><span class="p">(</span><span class="n">ICMP</span><span class="p">)</span>
<span class="go">2</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="c1"># access by index; notice no conversion to string</span>
<span class="go">&lt;switchyard.lib.packet.icmp.ICMP object at 0x104449c78&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="p">[</span><span class="n">ICMP</span><span class="p">]</span> <span class="c1"># access by header type</span>
<span class="go">&lt;switchyard.lib.packet.icmp.ICMP object at 0x104449c78&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="p">[</span><span class="n">ICMP</span><span class="p">]</span><span class="o">.</span><span class="n">icmptype</span>
<span class="go">&lt;ICMPType.EchoRequest: 8&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="p">[</span><span class="n">ICMP</span><span class="p">]</span><span class="o">.</span><span class="n">icmpcode</span>
<span class="go">&lt;EchoRequest.EchoRequest: 0&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="p">[</span><span class="n">ICMP</span><span class="p">]</span><span class="o">.</span><span class="n">icmpdata</span>
<span class="go">&lt;switchyard.lib.packet.icmp.ICMPEchoRequest object at 0x1044742c8&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">icmp</span><span class="o">.</span><span class="n">icmpdata</span><span class="o">.</span><span class="n">sequence</span>
<span class="go">0</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">icmp</span><span class="o">.</span><span class="n">icmpdata</span><span class="o">.</span><span class="n">identifier</span>
<span class="go">0</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">icmp</span><span class="o">.</span><span class="n">icmpdata</span><span class="o">.</span><span class="n">identifier</span> <span class="o">=</span> <span class="mi">42</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">icmp</span><span class="o">.</span><span class="n">icmpdata</span><span class="o">.</span><span class="n">sequence</span> <span class="o">=</span> <span class="mi">13</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span> <span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="go">Ethernet 00:00:00:00:00:00-&gt;00:11:22:33:44:55 IP | IPv4 0.0.0.0-&gt;149.43.80.13 ICMP | ICMP EchoRequest 42 13 (0 data bytes)</span>
</pre></div>
</div>
<p>By default, no &#8220;payload&#8221; data are included in with an ICMP header, but we can change that using the <code class="docutils literal"><span class="pre">data</span></code> property on the icmpdata part of the header:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">icmp</span><span class="o">.</span><span class="n">icmpdata</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="s2">&quot;hello, world&quot;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span> <span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="go">Ethernet 00:00:00:00:00:00-&gt;00:11:22:33:44:55 IP | IPv4 0.0.0.0-&gt;149.43.80.13 ICMP | ICMP EchoRequest 42 13 (12 data bytes)</span>
</pre></div>
</div>
<p>Python keyword argument syntax can be used to assign values to header fields when a header object is constructed.  This kind of syntax can make packet construction a bit more compact and streamlined.  For example, if we wanted to make a UDP packet with some payload, we could do something like the following:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">e</span> <span class="o">=</span> <span class="n">Ethernet</span><span class="p">(</span><span class="n">src</span><span class="o">=</span><span class="s2">&quot;11:22:33:44:55:66&quot;</span><span class="p">,</span> <span class="n">dst</span><span class="o">=</span><span class="s2">&quot;66:55:44:33:22:11&quot;</span><span class="p">,</span> <span class="n">ethertype</span><span class="o">=</span><span class="n">EtherType</span><span class="o">.</span><span class="n">IP</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ip</span> <span class="o">=</span> <span class="n">IPv4</span><span class="p">(</span><span class="n">src</span><span class="o">=</span><span class="s2">&quot;1.2.3.4&quot;</span><span class="p">,</span> <span class="n">dst</span><span class="o">=</span><span class="s2">&quot;4.3.2.1&quot;</span><span class="p">,</span> <span class="n">protocol</span><span class="o">=</span><span class="n">IPProtocol</span><span class="o">.</span><span class="n">UDP</span><span class="p">,</span> <span class="n">ttl</span><span class="o">=</span><span class="mi">32</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">udp</span> <span class="o">=</span> <span class="n">UDP</span><span class="p">(</span><span class="n">src</span><span class="o">=</span><span class="mi">1234</span><span class="p">,</span> <span class="n">dst</span><span class="o">=</span><span class="mi">4321</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">e</span> <span class="o">+</span> <span class="n">ip</span> <span class="o">+</span> <span class="n">udp</span> <span class="o">+</span> <span class="n">b</span><span class="s2">&quot;this is some application payload!&quot;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="go">Ethernet 11:22:33:44:55:66-&gt;66:55:44:33:22:11 IP | IPv4 1.2.3.4-&gt;4.3.2.1 UDP | UDP 1234-&gt;4321 | RawPacketContents (33 bytes) b&#39;this is so&#39;...</span>
<span class="go">&gt;&gt;&gt;</span>
</pre></div>
</div>
<p>Finally, to serialize the packet into a wire format sequence of bytes, we can use the <code class="docutils literal"><span class="pre">to_bytes()</span></code> method:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">to_bytes</span><span class="p">()</span>
<span class="go">b&#39;\x00\x11&quot;3DU\x00\x00\x00\x00\x00\x00\x08\x00E\x00\x00(\x00\x00\x00\x00\x00\x01\xba\xd6\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xb7|\x00*\x00\rhello, world&#39;</span>
</pre></div>
</div>
<p>Switchyard normally handles <em>deserialization</em> automatically, but there is a <code class="docutils literal"><span class="pre">from_bytes(raw)</span></code> method available that accepts a raw bytes object and reconstructs packet header attributes.  It either succeeds or throws an exception.  It returns any bytes that were not necessary for reconstructing the header.</p>
<p>As mentioned above, Switchyard does not require packets to be correctly constructed (e.g., there may be a TCP header in a packet without any IP header).  As a result, while serialization will often succeed even if the packet is malformed, whereas deserialization often will not.  The reason is that in deserialization, the contents of bytes earlier in a packet are necessary for determining how to reconstruct later headers and attributes in a packet (e.g., the <code class="docutils literal"><span class="pre">ethertype</span></code> attribute in the Ethernet header is necessary for determining which header comes next).</p>
<p>Other header classes that are available in Switchyard include <code class="docutils literal"><span class="pre">Arp</span></code>, <code class="docutils literal"><span class="pre">UDP</span></code>, <code class="docutils literal"><span class="pre">TCP</span></code>, <code class="docutils literal"><span class="pre">IPv6</span></code>, and <code class="docutils literal"><span class="pre">ICMPv6</span></code>.  Again, see the <a class="reference internal" href="reference.html#pktlib"><span class="std std-ref">packet library reference documentation</span></a> for details on these header classes, and full documentation for all classes.</p>
</div>
<div class="section" id="utility-functions">
<span id="utilityfns-label"></span><h2>Utility functions<a class="headerlink" href="#utility-functions" title="Permalink to this headline">¶</a></h2>
<p>There are a few additional utility functions that are useful when developing a Switchyard program related to logging and debugging.</p>
<div class="section" id="logging-functions">
<span id="logging-label"></span><h3>Logging functions<a class="headerlink" href="#logging-functions" title="Permalink to this headline">¶</a></h3>
<p>Switchyard uses Python&#8217;s standard logging facilities and provides four convenience functions.  Each of these functions takes a string as a parameter and prints it to the console as a logging message.  The only difference with the functions relates to the logging <em>level</em> (see <code class="xref py py-mod docutils literal"><span class="pre">logging</span></code> in the Python library reference), and whether the output is colored to visually highlight a problem.  The default logging level is INFO  within Switchyard.  If you wish to include debugging messages, you can use the <code class="docutils literal"><span class="pre">-d</span></code> flag for the various invocation programs (e.g., <code class="docutils literal"><span class="pre">swyard</span></code>), as described in <a class="reference internal" href="test_execution.html#runtest"><span class="std std-ref">Running in the test environment</span></a> and <a class="reference internal" href="live_execution.html#runlive"><span class="std std-ref">Running in a &#8220;live&#8221; environment</span></a>.</p>
<dl class="function">
<dt id="log_debug">
<code class="descname">log_debug</code><span class="sig-paren">(</span><em>str</em><span class="sig-paren">)</span><a class="headerlink" href="#log_debug" title="Permalink to this definition">¶</a></dt>
<dd><p>Write a debugging message to the log using the log level DEBUG.</p>
</dd></dl>

<dl class="function">
<dt id="log_info">
<code class="descname">log_info</code><span class="sig-paren">(</span><em>str</em><span class="sig-paren">)</span><a class="headerlink" href="#log_info" title="Permalink to this definition">¶</a></dt>
<dd><p>Write a debugging message to the log using the log level INFO.</p>
</dd></dl>

<dl class="function">
<dt id="log_warn">
<code class="descname">log_warn</code><span class="sig-paren">(</span><em>str</em><span class="sig-paren">)</span><a class="headerlink" href="#log_warn" title="Permalink to this definition">¶</a></dt>
<dd><p>Write a debugging message to the log using the log level WARNING.  Output
is colored magenta.</p>
</dd></dl>

<dl class="function">
<dt id="log_failure">
<code class="descname">log_failure</code><span class="sig-paren">(</span><em>str</em><span class="sig-paren">)</span><a class="headerlink" href="#log_failure" title="Permalink to this definition">¶</a></dt>
<dd><p>Write a debugging message to the log using the log level CRITICAL.  Output
is colored red.</p>
</dd></dl>

<p>While you can still use the built-in <code class="docutils literal"><span class="pre">print</span></code> function to write messages to the console, using the log functions provides a much more structured way of writing information to the screen.</p>
</div>
<div class="section" id="invoking-the-debugger">
<h3>Invoking the debugger<a class="headerlink" href="#invoking-the-debugger" title="Permalink to this headline">¶</a></h3>
<p>Although a longer discussion of debugging is included in <a class="reference internal" href="test_execution.html#debugging"><span class="std std-ref">a later section</span></a>, it is worth mentioning that there is a built-in function named <code class="docutils literal"><span class="pre">debugger</span></code> that can be used <em>anywhere</em> in Switchyard code to immediately invoke the standard Python pdb debugger.</p>
<p>For example, if we add a call to <code class="docutils literal"><span class="pre">debugger()</span></code> in the example code above just <em>after</em> the try/except block, then <a class="reference internal" href="test_execution.html#runtest"><span class="std std-ref">run the code in a test environment</span></a>, the program pauses immediately after the call to debugger and the pdb prompt is shown:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="c1"># after hub code is started in test environment,</span>
<span class="c1"># some output is shown, followed by this:</span>

<span class="o">&gt;</span> <span class="o">/</span><span class="n">Users</span><span class="o">/</span><span class="n">jsommers</span><span class="o">/</span><span class="n">Dropbox</span><span class="o">/</span><span class="n">src</span><span class="o">/</span><span class="n">switchyard</span><span class="o">/</span><span class="n">xhub</span><span class="o">.</span><span class="n">py</span><span class="p">(</span><span class="mi">29</span><span class="p">)</span><span class="n">main</span><span class="p">()</span>
<span class="o">-&gt;</span> <span class="k">for</span> <span class="n">port</span> <span class="ow">in</span> <span class="n">net</span><span class="o">.</span><span class="n">ports</span><span class="p">():</span>
<span class="p">(</span><span class="n">Pdb</span><span class="p">)</span> <span class="nb">list</span>
 <span class="mi">24</span>
 <span class="mi">25</span>                 <span class="n">debugger</span><span class="p">()</span>
 <span class="mi">26</span>
 <span class="mi">27</span>                 <span class="c1"># send the packet out all ports *except*</span>
 <span class="mi">28</span>                 <span class="c1"># the one on which it arrived</span>
 <span class="mi">29</span>  <span class="o">-&gt;</span>             <span class="k">for</span> <span class="n">port</span> <span class="ow">in</span> <span class="n">net</span><span class="o">.</span><span class="n">ports</span><span class="p">():</span>
 <span class="mi">30</span>                     <span class="k">if</span> <span class="n">port</span><span class="o">.</span><span class="n">name</span> <span class="o">!=</span> <span class="n">input_port</span><span class="p">:</span>
 <span class="mi">31</span>                         <span class="n">net</span><span class="o">.</span><span class="n">send_packet</span><span class="p">(</span><span class="n">port</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">packet</span><span class="p">)</span>
 <span class="mi">32</span>
</pre></div>
</div>
<p>As you can see, the program is paused on the next executable line following the call to <code class="docutils literal"><span class="pre">debugger()</span></code>.  At this point, any valid <code class="docutils literal"><span class="pre">pdb</span></code> commands can be given to inspect or alter program state.  Once again, see later sections for details on running Switchyard code <a class="reference internal" href="live_execution.html#runlive"><span class="std std-ref">in a live environment</span></a> and on other <a class="reference internal" href="test_execution.html#debugging"><span class="std std-ref">debugging capabilities</span></a>.</p>
</div>
</div>
<div class="section" id="passing-arguments-into-a-switchyard-program">
<span id="swyardargs"></span><span id="index-4"></span><h2>Passing arguments into a Switchyard program<a class="headerlink" href="#passing-arguments-into-a-switchyard-program" title="Permalink to this headline">¶</a></h2>
<p>It is possible to pass in additional arguments to a Switchyard program via its <code class="docutils literal"><span class="pre">main</span></code> function.  To accept additional arguments into your <code class="docutils literal"><span class="pre">main</span></code> function, you should <em>at least</em> add a <code class="docutils literal"><span class="pre">*args</span></code> parameter.  You can optionally also accept keyword-style arguments by including a <code class="docutils literal"><span class="pre">**kwargs</span></code> parameter.  For example, here is the initial part of a <code class="docutils literal"><span class="pre">main</span></code> function which accepts both:</p>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="n">netobj</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
    <span class="c1"># args is a list of arguments</span>
    <span class="c1"># kwargs is a dictionary of key-value keyword arguments</span>
</pre></div>
</div>
<p>As noted in the code comment, the parameter <code class="docutils literal"><span class="pre">*args</span></code> will collect any <em>non-keyword</em> arguments into a list and the parameter <code class="docutils literal"><span class="pre">**kwargs</span></code> will collect any keyword-style arguments into a dictionary.  Note that <em>all</em> argument values are passed in as strings, so your program may need to do some type conversion.</p>
<p>To pass arguments into your <code class="docutils literal"><span class="pre">main</span></code> function from invoking <code class="docutils literal"><span class="pre">swyard</span></code> on the command line, use the <code class="docutils literal"><span class="pre">-g</span></code> option.  This option accepts a string, which should include all arguments to be passed to your <code class="docutils literal"><span class="pre">main</span></code> function, each separated by spaces.  For keyword-style arguments, you can use the syntax <code class="docutils literal"><span class="pre">param=value</span></code>.  Any space-separated strings that do not include the <code class="docutils literal"><span class="pre">=</span></code> character as passed into the arglist (<code class="docutils literal"><span class="pre">args</span></code>).  For example, to pass in the value <code class="docutils literal"><span class="pre">13</span></code> and the keyword parameter <code class="docutils literal"><span class="pre">debug=True</span></code>, you could use the following command-line:</p>
<div class="highlight-none"><div class="highlight"><pre><span></span>$ swyard -g &quot;13 debug=True&quot; ... (other arguments to swyard)
</pre></div>
</div>
<p>When invoking your <code class="docutils literal"><span class="pre">main</span></code> function, <code class="docutils literal"><span class="pre">args</span></code> would have a single value (the string <code class="docutils literal"><span class="pre">'13'</span></code>) and <code class="docutils literal"><span class="pre">kwargs</span></code> would be the dictionary <code class="docutils literal"><span class="pre">{'debug':</span> <span class="pre">'True'}</span></code> (notice that <code class="docutils literal"><span class="pre">True</span></code> would be a string since all arguments end up being passed in as strings).</p>
<p class="rubric">Footnotes</p>
<table class="docutils footnote" frame="void" id="f1" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1">[1]</a></td><td>A hub is a network device with multiple physical ports.  Any packet
to arrive on a port is sent back out <em>all</em> ports <strong>except</strong> for the one
on which it arrived.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="f2" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id2">[2]</a></td><td><a class="reference external" href="https://github.com/noxrepo/pox">https://github.com/noxrepo/pox</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="f3" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id3">[3]</a></td><td><a class="reference external" href="https://github.com/osrg/ryu">https://github.com/osrg/ryu</a></td></tr>
</tbody>
</table>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="test_execution.html" title="Running in the test environment"
             >next</a> |</li>
        <li class="right" >
          <a href="intro.html" title="Introduction and Overview"
             >previous</a> |</li>
        <li class="nav-item nav-item-0"><a href="index.html">Switchyard 2017.01.5 documentation</a> &#187;</li> 
      </ul>
    </div>
    <div class="footer" role="contentinfo">
        &#169; Copyright 2013-2017, Joel Sommers.
      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.5.1.
    </div>
  </body>
</html>